home *** CD-ROM | disk | FTP | other *** search
- /* ilbmtoppm.c - read an IFF ILBM file and produce a portable pixmap
- **
- ** Copyright (C) 1989 by Jef Poskanzer.
- **
- ** Permission to use, copy, modify, and distribute this software and its
- ** documentation for any purpose and without fee is hereby granted, provided
- ** that the above copyright notice appear in all copies and that both that
- ** copyright notice and this permission notice appear in supporting
- ** documentation. This software is provided "as is" without express or
- ** implied warranty.
- **
- ** Modified by Mark Thompson on 10/4/90 to accomodate 24 bit IFF files
- ** as used by ASDG, NewTek, etc.
- */
-
- #import <stdio.h>
- #import <stdlib.h>
- #import <streams/streams.h>
- #import <strings.h>
- #import "kludge.h"
- #import "ilbm.h"
-
- static void getfourchars(NXStream* f, char fourchars[4]);
- static unsigned char get_byte( NXStream* f );
-
- void main(int argc, char *argv[])
- {
- NXStream* ifp;
- pixel* pixelrow;
- pixel* colormap = 0;
- int argn, colors, i, j, r, g, b, byte, bytes;
- short rows, cols = 0, row, col;
- int maxval;
- char iffid[5];
- unsigned char* body = 0;
- unsigned char* bp;
- unsigned char* ubp;
- unsigned char* rawrow;
- unsigned char* runbuf;
- unsigned char* Rrow;
- unsigned char* Grow;
- unsigned char* Brow;
- long formsize, bytesread, chunksize, viewportmodes = 0;
- int nPlanes, masking, compression, xAsp, yAsp, ham, hammask, allPlanes;
-
- /*
- ppm_init( &argc, argv );
-
- argn = 1;
-
- if ( argn < argc ) {
- ifp = pm_openr( argv[argn] );
- argn++;
- } else
- ifp = stdin;
-
- if ( argn != argc )
- pm_usage( "[ilbmfile]" );
- */
- ifp = pm_openr( argv[argn] );
-
- /* Read in the ILBM file. */
- iffid[4] = '\0';
- getfourchars( ifp, iffid );
- if ( strcmp( iffid, "FORM" ) != 0 )
- pm_error( "input is not a FORM type IFF file" );
- if ( pm_readbiglong( ifp, &formsize ) == -1 )
- pm_error( "EOF / read error" );
- getfourchars( ifp, iffid );
- if ( strcmp( iffid, "ILBM" ) != 0 )
- pm_error( "input is not an ILBM type FORM IFF file" );
- bytesread = 12;
-
- /* Main loop, parsing the IFF FORM. */
- while ( bytesread < formsize ) {
- getfourchars( ifp, iffid );
- if ( pm_readbiglong( ifp, &chunksize ) == -1 )
- pm_error( "EOF / read error" );
- bytesread += 8;
-
- if ( body != 0 ) {
- fprintf(stderr, "\"%s\" chunk found after BODY chunk - skipping", iffid );
- for ( i = 0; i < chunksize; i++ )
- (void) get_byte( ifp );
- } else if ( strcmp( iffid, "BMHD" ) == 0 ) {
- short junk;
- if ( pm_readbigshort( ifp, &cols ) == -1 )
- pm_error( "EOF / read error" );
- if ( pm_readbigshort( ifp, &rows ) == -1 )
- pm_error( "EOF / read error" );
- if ( pm_readbigshort( ifp, &junk ) == -1 )
- pm_error( "EOF / read error" );
- if ( pm_readbigshort( ifp, &junk ) == -1 )
- pm_error( "EOF / read error" );
- nPlanes = get_byte( ifp );
- masking = get_byte( ifp );
- compression = get_byte( ifp );
- (void) get_byte( ifp ); /* pad1 */
- if ( pm_readbigshort( ifp, &junk ) == -1 ) /* transparentColor */
- pm_error( "EOF / read error" );
- xAsp = get_byte( ifp );
- yAsp = get_byte( ifp );
- if ( pm_readbigshort( ifp, &junk ) == -1 ) /* pageWidth */
- pm_error( "EOF / read error" );
- if ( pm_readbigshort( ifp, &junk ) == -1) /* pageHeight */
- pm_error( "EOF / read error" );
- } else if ( strcmp( iffid, "CMAP" ) == 0 ) {
- colors = chunksize / 3;
- if ( colors > 0 ) {
- colormap = ppm_allocrow( colors );
- for ( i = 0; i < colors; i++ ) {
- r = get_byte( ifp );
- g = get_byte( ifp );
- b = get_byte( ifp );
- PPM_ASSIGN( colormap[i], r, g, b );
- }
- if ( colors * 3 != chunksize )
- (void) get_byte( ifp );
- }
- } else if ( strcmp( iffid, "CAMG" ) == 0 ) {
- if ( pm_readbiglong( ifp, &viewportmodes ) == -1 )
- pm_error( "EOF / read error" );
- } else if ( strcmp( iffid, "BODY" ) == 0 ) {
- body = (unsigned char*) malloc( chunksize );
- if ( body == 0 )
- pm_error( "out of memory" );
- if ( fread( body, 1, chunksize, ifp ) != chunksize )
- pm_error( "EOF / read error reading BODY chunk" );
- } else if ( strcmp( iffid, "GRAB" ) == 0 ||
- strcmp( iffid, "DEST" ) == 0 ||
- strcmp( iffid, "SPRT" ) == 0 ||
- strcmp( iffid, "CRNG" ) == 0 ||
- strcmp( iffid, "CCRT" ) == 0 ||
- strcmp( iffid, "DPPV" ) == 0 ) {
- for ( i = 0; i < chunksize; i++ )
- (void) get_byte( ifp );
- } else {
- fprintf(stderr, "unknown chunk type \"%s\" - skipping", iffid );
- for ( i = 0; i < chunksize; i++ )
- (void) get_byte( ifp );
- }
-
- bytesread += chunksize;
- }
-
- pm_close( ifp );
-
- /* Done reading. Now interpret what we got. */
- if ( cols == 0 )
- pm_error( "no BMHD chunk found" );
- if ( body == 0 )
- pm_error( "no BODY chunk found" );
- if ( xAsp != yAsp )
- fprintf(stderr, "warning - non-square pixels; to fix do a 'pnmscale -%cscale %g'",
- xAsp > yAsp ? 'x' : 'y',
- xAsp > yAsp ? (float) xAsp / yAsp : (float) yAsp / xAsp );
- if ( ( viewportmodes & vmHAM ) && nPlanes != 24 ) {
- ham = 1;
- hammask = ( 1 << ( nPlanes - 2 ) ) - 1;
- maxval = pm_bitstomaxval( nPlanes - 2 );
- if ( maxval > PPM_MAXMAXVAL )
- pm_error("nPlanes is too large - try reconfiguring with PGM_BIGGRAYS\n or without PPM_PACKCOLORS" );
- if ( colormap != 0 )
- for ( i = 0; i < colors; i++ ) {
- r = PPM_GETR( colormap[i] ) >> ( 10 - nPlanes );
- g = PPM_GETG( colormap[i] ) >> ( 10 - nPlanes );
- b = PPM_GETB( colormap[i] ) >> ( 10 - nPlanes );
- PPM_ASSIGN( colormap[i], r, g, b );
- }
- } else {
- ham = 0;
- if ( colormap != 0 )
- maxval = 255; /* colormap contains bytes */
- else if ( nPlanes == 24 )
- maxval = 255;
- else
- maxval = pm_bitstomaxval( nPlanes );
- if ( maxval > PPM_MAXMAXVAL )
- pm_error("nPlanes is too large - try reconfiguring with PGM_BIGGRAYS\n or without PPM_PACKCOLORS" );
- }
- if ( viewportmodes & vmEXTRA_HALFBRITE ) {
- pixel* tempcolormap;
-
- tempcolormap = ppm_allocrow( colors * 2 );
- for ( i = 0; i < colors; i++ ) {
- tempcolormap[i] = colormap[i];
- PPM_ASSIGN(tempcolormap[colors + i], PPM_GETR(colormap[i]) / 2,
- PPM_GETG(colormap[i]) / 2, PPM_GETB(colormap[i]) / 2 );
- }
- ppm_freerow( colormap );
- colormap = tempcolormap;
- colors *= 2;
- }
- if ( colormap == 0 && nPlanes != 24 )
- fprintf(stderr, "no colormap - interpreting values as grayscale" );
- allPlanes = nPlanes + ( masking == mskHasMask ? 1 : 0 );
-
- ppm_writeppminit( stdout, cols, rows, (pixval) maxval, 0 );
- pixelrow = ppm_allocrow( cols );
- if ( nPlanes == 24 ) {
- Rrow = (unsigned char*) malloc( cols );
- Grow = (unsigned char*) malloc( cols );
- Brow = (unsigned char*) malloc( cols );
- if ( Rrow == 0 || Grow == 0 || Brow == 0 )
- pm_error( "out of memory" );
- } else {
- rawrow = (unsigned char*) malloc( cols );
- if ( rawrow == 0 )
- pm_error( "out of memory" );
- }
- runbuf = (unsigned char*) malloc( RowBytes( cols ) );
- if ( runbuf == 0 )
- pm_error( "out of memory" );
-
- bp = body;
- for ( row = 0; row < rows; row++ ) {
- /* Extract rawrow from the image. */
- if ( nPlanes == 24 )
- for ( col = 0; col < cols; ++col )
- Rrow[col] = Grow[col] = Brow[col] = 0;
- else
- for ( col = 0; col < cols; ++col )
- rawrow[col] = 0;
- for ( i = 0; i < allPlanes; i++ ) {
- switch ( compression ) {
- case cmpNone:
- ubp = bp;
- bp += RowBytes( cols );
- break;
-
- case cmpByteRun1:
- ubp = runbuf;
- bytes = RowBytes( cols );
- do {
- byte = *bp++;
- if ( byte <= 127 )
- for ( j = byte, bytes -= j + 1; j >= 0; j-- )
- *ubp++ = *bp++;
- else if ( byte != 128 )
- for ( j = 256 - byte, bytes -= j + 1, byte = *bp++; j >= 0; j-- )
- *ubp++ = byte;
- }
- while ( bytes > 0 );
- if ( bytes < 0 )
- pm_error( "error doing ByteRun decompression" );
- ubp = runbuf;
- break;
-
- default:
- pm_error( "unknown compression type" );
- }
-
- if ( i >= nPlanes )
- continue; /* ignore mask plane */
-
- if ( nPlanes == 24 ) {
- for ( col = 0; col < cols; col++ )
- if ( i < 8 ) { /* red */
- if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
- Rrow[col] |= 1 << i;
- } else if ( i > 15 ) { /* blue */
- if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
- Brow[col] |= 1 << (i-16);
- } else { /* green */
- if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
- Grow[col] |= 1 << (i-8);
- }
- } else
- for ( col = 0; col < cols; col++ )
- if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
- rawrow[col] |= 1 << i;
- }
-
- /* Interpret rawrow into pixels. */
- r = g = b = 0;
- for ( col = 0; col < cols; col++ )
- if ( ham ) { /* HAM mode. */
- switch ( ( rawrow[col] >> nPlanes - 2 ) & 0x3 ) {
- case 0:
- if ( colormap != 0 && colors >= maxval )
- pixelrow[col] = colormap[rawrow[col] & hammask];
- else
- PPM_ASSIGN(pixelrow[col], rawrow[col] & hammask,
- rawrow[col] & hammask, rawrow[col] & hammask );
- r = PPM_GETR( pixelrow[col] );
- g = PPM_GETG( pixelrow[col] );
- b = PPM_GETB( pixelrow[col] );
- break;
-
- case 1:
- b = rawrow[col] & hammask;
- PPM_ASSIGN( pixelrow[col], r, g, b );
- break;
-
- case 2:
- r = rawrow[col] & hammask;
- PPM_ASSIGN( pixelrow[col], r, g, b );
- break;
-
- case 3:
- g = rawrow[col] & hammask;
- PPM_ASSIGN( pixelrow[col], r, g, b );
- break;
-
- default:
- pm_error( "impossible HAM code" );
- }
- } else if ( nPlanes == 24 )
- /* 24bit image. */
- PPM_ASSIGN( pixelrow[col], Rrow[col], Grow[col], Brow[col] );
- else if ( colormap != 0 )
- /* Non-HAM colormapped. */
- pixelrow[col] = colormap[rawrow[col]];
- else
- /* Non-HAM direct - weird. */
- PPM_ASSIGN(pixelrow[col], rawrow[col], rawrow[col], rawrow[col] );
-
- /* And write out the row. */
- ppm_writeppmrow( stdout, pixelrow, cols, (pixval) maxval, 0 );
- }
-
- exit( 0 );
- }
-
- static unsigned char get_byte(NXStream *f)
- {
- int i;
-
- i = NXGetc( f );
- if ( i == EOF )
- pm_error( "EOF / read error" );
-
- return (unsigned char) i;
- }
-
- static void getfourchars(NXStream *f, char fourchars[4])
- {
- fourchars[0] = get_byte( f );
- fourchars[1] = get_byte( f );
- fourchars[2] = get_byte( f );
- fourchars[3] = get_byte( f );
- }
-